import io
from datetime import timedelta

from aiogram import Bot, Dispatcher, F
from aiogram.filters.text import Text
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import any_state
from aiogram.types import Message, ReplyKeyboardRemove
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import sessionmaker

from app.bot.keyboards.reply import unblock_more_keyboard, user_keyboard
from app.bot.states.states import Accounts
from app.bot.utils.date_time import get_date_time
from app.bot.utils.logger import log
from app.bot.utils.scheduler import jobs
from app.database.functions.account import add_account, get_account_by_login
from app.database.functions.stats import update_stats, update_user_stats


async def start_unban(message: Message, state: FSMContext) -> None:
    """
    Добавление аккаунтов
    """

    txt = (
        f"Бот сам разберется, что необходимо сделать с Вашим аккаунтом. Если аккаунт действительно заблокирован сам и вы не можете в него войти, либо на нем заблокирован рекламный кабинет, бот пройдет любой чек за Вас в автоматическом режиме\n\n"
        f"Если вы хотите разблокировать 1 аккаунт, отправьте мне его в формате: <b>login|pass|email|email_pass|user_agent</b>\n\n"
        f"Если аккаунтов больше, то в таком случае необходимо отправить мне txt файл, в котором необходимо указать каждый аккаунт в новой строчке, например:\n"
        f"<b>login|pass|email|email_pass|user_agent</b>\n"
        f"<b>login|pass|email|email_pass|user_agent</b>\n"
        f"<b>login|pass|email|email_pass|user_agent</b>\n"
        f"<b>login|pass|email|email_pass|user_agent</b>\n\n"
        f"Если каких то данные не хватает то просто оставляете пустым его например - \n"
        f"<b>login|pass|email||user_agent</b>\n"
        f"<b>login|pass</b>\n"
        f"<b>login|pass|||user_agent</b>\n\n"
        f"Можете просто отправить мне <b>login|pass</b>, если другие данные отсутствуют. В любом случае, я выдам вам уведомление о результате работы с каждым аккаунтом\n\n"
        f"<b>Бот работает только с почтами kopeechka.store!</b>\n"
    )

    await message.answer(txt, reply_markup=ReplyKeyboardRemove())
    await message.answer("Отправьте /cancel, чтобы вернуться в главное меню")
    await state.set_state(Accounts.waiting_accounts)


async def send_accounts(
    message: Message,
    bot: Bot,
    session: AsyncSession,
    session_factory: sessionmaker,
    scheduler: AsyncIOScheduler,
    state: FSMContext,
) -> None:
    """
    Ждем от пользователя ввод аккаунтов текстом, либо файл с аккаунтами
    """

    if not message.document and not message.text:
        await message.answer("Вы не прислали файл или текстовый список аккаунтов")
        await state.set_state(Accounts.waiting_accounts)
        return

    if message.document:
        if ".txt" not in message.document.file_name:
            await message.answer("Вы прислали не txt файл")
            await state.set_state(Accounts.waiting_accounts)
            return
        else:
            file = io.BytesIO()
            await bot.download(message.document, destination=file)
            file_text = [line.decode() for line in file.readlines()]
            if "|" not in str(file_text):
                txt = (
                    f"В файле отсутствует разделитель <b>|</b>\n"
                    f"Пожалуйста, проверьте файл и загрузите его заново\n"
                )
                await message.answer(txt)
                await state.set_state(Accounts.waiting_accounts)
                return
            else:
                accounts = [list(account.strip().split("|")) for account in file_text]
                for account in accounts:
                    if len(account) != 5:
                        await message.answer(
                            f"Аккаунт {'|'.join(account)} не был добавлен, так как вы не указали пропуск вместо недостающего значения(ий)"
                        )
                        accounts.remove(account)
                    else:
                        account.insert(0, message.from_user.id)
                        account.insert(1, "tg")
                        # await db_requests.add_account(account)
                if len(accounts) > 1:
                    await message.answer(
                        f"Взял в работу аккаунтов: {len(accounts)} аккаунтов. По каждому из них вы получите результат в течение 40 минут",
                        reply_markup=unblock_more_keyboard(),
                    )
                elif len(accounts) > 0:
                    await message.answer(
                        "Аккаунт добавлен в работу. Вы получите результат по нему в течение 40 минут",
                        reply_markup=unblock_more_keyboard(),
                    )
                else:
                    await message.answer(
                        "Ни один из аккаунтов не попал в работу, исправьте ошибки и загрузите их снова",
                        reply_markup=user_keyboard(),
                    )
                    await state.set_state(Accounts.waiting_accounts)
                    return

    elif message.text:
        if "|" not in message.text:
            txt = (
                f"В списке отсутствует разделитель <b>|</b>\n"
                f"Пожалуйста, проверьте список и отправьте его заново\n"
            )
            await message.answer(txt)
            await state.set_state(Accounts.waiting_accounts)
            return
        else:
            accounts = [
                list(account.strip().split("|")) for account in message.text.split("\n")
            ]
            for account in accounts:
                if len(account) != 5:
                    await message.answer(
                        f"Аккаунт {'|'.join(account)} не был добавлен, так как вы не указали пропуск вместо недостающего значения(ий)"
                    )
                    accounts.remove(account)
                else:
                    account.insert(0, message.from_user.id)
                    account.insert(1, "tg")
                    if not await get_account_by_login(
                        session, account_login=account[2]
                    ):
                        await add_account(session, account)
                    else:
                        accounts.remove(account)
                        await message.answer(
                            f"Аккаунт с логином {account[2]} уже есть в базе данных"
                        )

            if len(accounts) > 1:
                await message.answer(
                    f"Взял в работу аккаунтов: {len(accounts)}. По каждому из них вы получите результат в течение 40 минут",
                    reply_markup=unblock_more_keyboard(),
                )
            elif len(accounts) > 0:
                await message.answer(
                    "Аккаунт добавлен в работу. Вы получите результат по нему в течение 40 минут",
                    reply_markup=unblock_more_keyboard(),
                )
            else:
                await message.answer(
                    "Ни один из аккаунтов не попал в работу, исправьте ошибки и загрузите их снова"
                )
                await state.set_state(Accounts.waiting_accounts)
                return

    time_limit = get_date_time(get_datetime=True) + timedelta(minutes=40)

    scheduler.add_job(
        jobs.notify_user,
        "interval",
        name="Accounts",
        seconds=30,
        args=(
            bot,
            session_factory,
            scheduler,
            message.from_user.id,
            time_limit,
        ),
    )
    log.info(
        f"Добавлена задача на проверку аккаунтов для пользователя {message.from_user.id}"
    )
    await update_stats(
        session,
        accounts=len(accounts),
    )
    await update_user_stats(session, message.from_user.id, accounts_added=len(accounts))
    await state.clear()


async def add_more(message: Message, state: FSMContext) -> None:
    """
    Добавить еще аккаунты
    """

    txt = (
        f"Добавьте аккаунты по одному в каждой строке с разделителем |\n"
        f"Вы также можете загрузить txt файл с аккаунтами\n"
        f"Пример: <b>login|pass|email|email_pass|user_agent</b>\n"
    )

    await message.answer(txt, reply_markup=ReplyKeyboardRemove())
    await state.set_state(Accounts.waiting_accounts)


def register_accounts_handlers(dp: Dispatcher):
    dp.message.register(
        start_unban,
        Text(text="👤 Разблокировать FB аккаунт(ы)", ignore_case=True),
        any_state,
    )
    dp.message.register(
        send_accounts,
        F.content_type.in_(["text", "document"]),
        Accounts.waiting_accounts,
    )
    dp.message.register(
        add_more,
        Text(text="Разблокировать еще аккаунт(ы)", ignore_case=True),
        any_state,
    )
